using System;
using System.Data;
using System.Collections.Generic;
using System.Threading;
using MongoDB.Driver;
using MongoDB.Bson;
using Levi.Finance.Server.Common;
namespace Levi.Finance.Server.Data
{
	public class MongoDB : IDisposable
	{
		public MongoServer server = null;
		MongoCollection recordsCollection = null;
		MongoCursor<BsonDocument> rs = null;
		public bool Connecting { get; set; }
		public MongoDatabase database = null;
		ABC f;

		public MongoServerState State
		{
			get
			{
				if (server == null) return MongoServerState.None;
				else return server.State;
			}
		}

		public MongoDB(ABC _f)
		{
			f = _f;
			Connecting = false;
			server = MongoServer.Create(Connectionstring);
		}
		public void OpenMongoDBA()
		{
			OpenMongoDB();
		}
		public bool OpenMongoDB()
		{
			if (Connecting) return false;
			bool _try = true;
			Connecting = true;

			while (_try)
			{
				try
				{
					server.Connect();
					database = server.GetDatabase(f.configure.db_mongodb_database);
					_try = false;
					Connecting = false;
					f.onOutputText("connected to database.", 1);
				}
				catch (Exception ex)
				{
					f.onThreadException(this, new System.Threading.ThreadExceptionEventArgs(ex));
					f.onOutputText("unable connect to database!!!", -1);
					if (ex.ToString().Contains("Server is not a primary and SlaveOk is false"))
						f.onOutputText("configure database error, database is slave, but server run as master!!!", -1);
					else
						f.onOutputText("retry connect to database in 5 secounds after.");
					Thread.Sleep(5000);
				}
			}
			return true;
		}
		public string Connectionstring
		{
			get
			{
				MongoConnectionStringBuilder stringBuilder = new MongoConnectionStringBuilder();
				stringBuilder.Username = f.configure.db_mongodb_username;
				stringBuilder.Password = f.configure.db_mongodb_password;
				stringBuilder.Server = new MongoServerAddress(f.configure.db_mongodb_server);
				stringBuilder.DatabaseName = f.configure.db_mongodb_database;
				return stringBuilder.ConnectionString;
			}
		}
		public MongoCollection GetRecordsCollection()
		{
			while (true)
			{
				try
				{
					if (server.State == MongoServerState.Disconnected) if (!OpenMongoDB()) return null;
					if (recordsCollection == null)
					{
						database = server.GetDatabase(f.configure.db_mongodb_database);
						recordsCollection = database.GetCollection<BsonDocument>("records");
					}
					return recordsCollection;
				}
				catch
				{
					if (server.State == MongoServerState.Disconnected) if (!OpenMongoDB()) return null;
				}
			}
		}

		public MongoCursor<BsonDocument> GetList(string collection, IMongoQuery sql = null, string dbname = null)
		{
			while (true)
			{
				try
				{
					if (server.State == MongoServerState.Disconnected) if (!OpenMongoDB()) return null;
					recordsCollection = null;
					string dbName = dbname == null ? f.configure.db_mongodb_database : dbname;
					database = server.GetDatabase(dbName);
					recordsCollection = database.GetCollection<BsonDocument>(collection);
					if (null == sql)
					{
						rs = recordsCollection.FindAllAs<BsonDocument>();
					}
					else
					{
						rs = recordsCollection.FindAs<BsonDocument>(sql);
					}
					return rs;
				}
				catch
				{
					if (server.State == MongoServerState.Disconnected) if (!OpenMongoDB()) return null;
				}
			}
		}

		#region IDisposable 成员

		public void Dispose()
		{
			f.onOutputText("close database connection.", 1);
			server.Disconnect();
		}

		#endregion
	}
}

